﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Data;
using vudu.ClasesDominio;
using vudu.Presentacion.Contrato.VU_03_Gestionar_Pensum_por_Escuela;
using vudu.Logica.Fachada;
using vudu.Logica.Excepciones;

namespace vudu.Presentacion.Presentador.VU_03_Gestionar_Pensum_por_Escuela
{
    public class PresentadorCrearPensumEtapaI
    {
        #region Atributos Privados

        public IContratoCrearPensumEtapaI _vista;
        private EnlaceLogico _fachada;
        private List<Materia> _lista;
        private Pensum _pensumActual;
        private List<Materia> _materiasDePensum;
        private bool _etapaI;
        private bool _seleccioneAlgo;
        private Escuela _usuarioEscuela;
        private string _rol;

        #endregion

        #region Constructor

        public PresentadorCrearPensumEtapaI(IContratoCrearPensumEtapaI vista)
        {
            _vista = vista;
            _fachada = (EnlaceLogico)_vista.Sesion["Fachada"];
            if(_fachada!=null)
                _usuarioEscuela = (Escuela)_fachada.RolActual;
            _rol = (string)_vista.Sesion["TipoRol"];
            _etapaI = true;
            _lista = new List<Materia>();
            _materiasDePensum = new List<Materia>();
            _pensumActual = new Pensum();
            _seleccioneAlgo = false;
            _materiasDePensum = _vista.Sesion["MateriasParaPensum"] as List<Materia>;
        }

        #endregion

        #region Propiedades


        public Pensum PensumActual
        {
            get { return _pensumActual; }
            set { _pensumActual = value; }
        }

        public List<Materia> MateriasDePensum
        {
            get { return _materiasDePensum; }
            set { _materiasDePensum = value; }
        }

        public bool EtapaI
        {
            get { return _etapaI; }
            set { _etapaI = value; }
        }

        public string Rol
        {
            get { return _rol; }
            set { _rol = value; }
        }
        
        #endregion

        #region Metodos

        /// <summary>
        /// metodo que se encarga de escribir el nombre del usuario logeado
        /// </summary>
        public void MostrarNombreUsuario()
        {
            Escuela esc = (Escuela)_fachada.RolActual;
            _vista.Actor.Text = _rolUsuario + _separador + esc.NombreEscuela;
        }
        /// <summary>
        /// metodo que se encargara de crear el objeo pensum y realizar el comando de insertarlo al sistema
        /// con los datos basicos:id(obtenido del comando), numero de semestres, y una lista de materias
        /// el cual proseguira a la ventana de CrearPensumEtapaII
        /// </summary>
        public void CrearNuevoPensum()
        {

            MateriasDePensum = _vista.Sesion["MateriasParaPensum"] as List<Materia>;
            if (HayMateriasCargadas())
            {
                try
                {
                    string tipo = "";
                    string fechaActual = "";
                    tipo = _vista.TipoSemestre.SelectedItem.Text;//si pregunto por tipo(trimestrar, anual, semestral)
                    //int totalSemestres = int.Parse(_vista.TipoSemestre.SelectedItem.Text);//si pregunto el numero
                    fechaActual = System.DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
                    DateTime fecha = Convert.ToDateTime(fechaActual);
                    _pensumActual.FechaInicio = fecha;
                    _pensumActual.IdEscuela = _usuarioEscuela.IdEscuela;
                    _pensumActual.StatusPensum = "DESACTIVADO";
                    if (SeAgregoPensum(_pensumActual))
                    {
                        //si se cargo el pensum en base de datos y existen materias seleccionadas
                        //entonces puedo continuar a la etapa II
                        _vista.Sesion["PensumAConsultar"] = _pensumActual;
                        _vista.Sesion["numeroEtapa"] = 2;//actualizo el numero de la siguiente etapa
                        _etapaI = false;
                    }
                    else
                    {
                        OcurreError(_mensajeError1);//"Ha Ocurrido un error al Crear el Pensum"
                    }
                }
                catch (CreacionPensumException)
                {
                    OcurreError(_mensajeError2);//"Ha Ocurrido una Excepcion Inesperada"
                }
            }
            else
            {
                OcurreError(_mensajeError3);//"Debe seleccionar por lo menos 5 materias"
            }
        }

        /// <summary>
        /// Metodo que se encarga de validar que se hallan seleccionado materias
        /// para agregar al pensum
        /// </summary>
        /// <returns>
        /// true: hay mas de 5 materias escogidas
        /// false: hay menos de 5
        /// </returns>
        public bool HayMateriasCargadas()
        {
            bool resp = false;
            if (_materiasDePensum != null)
            {
                if (_materiasDePensum.Count >= _cantidadMinimaDeMaterias)
                {
                    resp = true;
                }
            }
            return resp;
        }

        /// <summary>
        /// metodo que pregunta si se agrego el objeto pensum en la base de datos
        /// </summary>
        /// <param name="pensumActual"></param>
        /// <returns></returns>
        public bool SeAgregoPensum(Pensum pensumActual)
        {
            bool resp = false;
            int seInserto = 0;
            seInserto = _fachada.CrearPensum(_pensumActual);
            if (seInserto > 0)
                resp = true;
            return resp;
        }
        public int totalSemestre()
        {
            return 0;
        }
        /// <summary>
        /// metodo que evalua hacia el estado de la pagina(etapaI)
        /// si al momento de agregar el pensum y haber cumplido con las validaciones 
        /// necesarias para seguir a la siguiente etapa
        /// </summary>
        /// <returns>
        /// "CrearPensumEtapaII.aspx" si la etapaI murio(es false)
        /// "CrearPensumEtapaI.aspx"; si la etapaI sigue estando vigente(true)
        /// </returns>
        public string Redireccionar()
        {
            string redireccionarA = "";
            if (_etapaI)
                redireccionarA = _paginaActual;
            else
                redireccionarA = _paginaSiguiente;
            return redireccionarA;
        }

        /// <summary>
        /// metodo que se encarga de la paginacion del gridview de materia
        /// </summary>
        /// <param name="e"></param>
        public void Paginacion(GridViewPageEventArgs e )
        {
            this._vista.TablaMaterias.PageIndex = e.NewPageIndex;
            this.CargarMateriasDeEscuela();
        }

        /// <summary>
        /// metodo que se encarga de la paginacion del gridview de materia
        /// </summary>
        /// <param name="e"></param>
        public void Paginacion2(GridViewPageEventArgs e, List<Materia> materiasEscogidas)
        {
            this._vista.TablaMateriasPensum.PageIndex = e.NewPageIndex;
            _materiasDePensum = materiasEscogidas;
            CargarTablaMateriasParaPensum();

            //this.CargarMateriasDeEscuela();
        }

        /// <summary>
        /// metodo que se encarga de llenar la lista de escuela que pertenescan
        /// a la misma universidad a la cual forma parte mi usuario escuela
        /// </summary>
        public void CargarListaEscuela()
        {
            try
            {
                List<Escuela> escuelas = new List<Escuela>();
                escuelas = _fachada.ConsultarEscuelasVecinas(_usuarioEscuela.IdEscuela);
                _vista.ListaEscuelas.DataSource = escuelas;
                _vista.ListaEscuelas.DataTextField = "NombreEscuela";
                _vista.ListaEscuelas.DataValueField = "IdEscuela";
                _vista.ListaEscuelas.DataBind();

            }
            catch (NullReferenceException)
            {
                OcurreError(_mensajeError2);//Excepcion
            }
            catch (Exception)
            {
                OcurreError(_mensajeError2);//Excepcion
            }

        }

        /// <summary>
        /// metodo que se encarga de obtener los valores de la fila del gridview de materias
        /// y asigna los valores de cada celda al objeto materia
        /// </summary>
        /// <param name="row"></param>
        /// <param name="mat"></param>
        /// <returns></returns>
        private Materia ObtenerMateriaDeFila(GridViewRow row, Materia mat)
        {
            try
            {
                string nombreMat = row.Cells[1].Text;
                string codMat = row.Cells[2].Text;
                string uc = row.Cells[3].Text;
                if (!uc.Contains('-') && !codMat.Contains('-'))
                {
                    mat.Nombre = nombreMat;
                    mat.Codigo = int.Parse(codMat);
                    mat.NumeroCreditos = int.Parse(uc);
                }
            }
            catch (Exception)
            {
                mat = null;
                OcurreError(_mensajeError2);//Excepcion
            }
            return mat;
        }

        /// <summary>
        /// metodo que se encarga de leerl alista de materias que se cargaran en el pensum
        /// </summary>
        /// <param name="mat">Materia a evaluar</param>
        /// <returns>true si la materia ya esta en la lista</returns>
        private bool EsMateriaRepetida( Materia mat , List<Materia> materias)
        {
            bool resp = false;

            if (( mat != null ) && ( materias != null ))
            {
                foreach(Materia materiaActual in materias)
                {
                    if (materiaActual.Codigo == mat.Codigo)
                    {
                        resp = true;
                    }
                }

            }
            return resp;
        }

        /// <summary>
        /// Al momento de precionar el boton "agregar" la vista llama al presentador que realiza el
        /// metodo que se encarga de buscar en el gridview de materias
        /// y escoge las materias que hallan sido seleccionadas por un check
        /// para agregarlas en una lista de materias que se almacenan en el presentador
        /// </summary>
        public void AgregarMateriaAPensum()
        {
            //obtengo la lista de materias quehansido seleccionadas hasta los momentos 
            MateriasDePensum = _vista.Sesion["MateriasParaPensum"] as List<Materia>;
            //la primera vez que cargue la pagina el session asignara a la lista como null
            //por eso la inicializamos nuevamente
            if (_materiasDePensum == null)
            {
                _materiasDePensum = new List<Materia>();
            }
            //recorro el gridview y saco la lista de materias seleccionadas
            foreach (GridViewRow row in _vista.TablaMaterias.Rows)
            {
                CheckBox check = row.FindControl("chkSeleccionEscoger") as CheckBox;
                if (check.Checked)
                {
                    _seleccioneAlgo = true;
                    Materia mat = new Materia();
                    mat = ObtenerMateriaDeFila(row, mat);
                    if (!EsMateriaRepetida(mat, _materiasDePensum))
                    {
                        _materiasDePensum.Add(mat);
                    }
                    check.Checked = false;
                }
            }
            ValidarSeleccionMateria();
        }

        private void ValidarSeleccionMateria()
        {
            if (_seleccioneAlgo == false)
            {
                OcurreError(_mensajeError4);//no ha seleccionado ninguna materia
                _vista.MensajeSeleccionar.ForeColor = System.Drawing.Color.Red;
                _vista.MensajeSeleccionar.Visible = true;
            }
            else
            {
                OcurreExito();//se agrego la materia a la lista exisotamente
                _vista.MensajeSeleccionar.ForeColor = System.Drawing.Color.Black;
                _vista.MensajeSeleccionar.Visible = true;
                _seleccioneAlgo = false;
            }

            
        }

        /// <summary>
        /// metodo que Carga la tabla de materia que pertenescan a la escuela seleccionada por dropdownlist
        /// </summary>
        public void CargarMateriasDeEscuela()
        {
            try
            {
                int idEscuelaSelec = int.Parse(_vista.ListaEscuelas.SelectedValue);
                if (idEscuelaSelec != 0)
                {
                    _lista = _fachada.ConsultarMateriasDeEscuela(idEscuelaSelec);
                    CargarTablaMaterias(_lista);
                }

            }
            catch (NullReferenceException)
            {
                OcurreError(_mensajeError2);//Excepcion
                //CargarTablaMaterias();
            }
            catch (Exception)
            {
                OcurreError(_mensajeError2);//Excepcion
                //CargarTablaMaterias();
            }
        }

        /// <summary>
        /// metodo que se encarga de calcular la diferencia entre el numero de materias traidas y el numero de filas total(8)
        /// para ayudar a rellenar las filas vacias del gridview de materia
        /// </summary>
        /// <param name="totalFilas"></param>
        /// <returns></returns>
        private int Diferencia(int totalFilas)
        {
            int diferencia = 0;
            if (totalFilas < _numeroFilas)
            {
                diferencia = _numeroFilas - totalFilas;
            }
            return diferencia;
        }

        /// <summary>
        /// Cargael Gridview con las materias dependiendo de la informacionque se encuentre en la 
        /// lista "_lsita" la cual contiene la lista de materias pertenecientes a la escuela
        /// seleccionada por el dropdwonlist
        /// </summary>
        public void CargarTablaMaterias(List<Materia> materias)
        {
            DataTable table = new DataTable();
            int diferencia = 0;
            table.Columns.Add("Nombre", typeof(string));
            table.Columns.Add("Codigo", typeof(string));
            table.Columns.Add("U.C.", typeof(string));
            try
            {   
                if (materias != null)
                {
                    diferencia = Diferencia(materias.Count);
                    foreach (Materia materia in materias)
                    {
                        String nombreMateria = materia.Nombre;
                        if (nombreMateria != null)
                        {
                            table.Rows.Add(materia.Nombre, materia.Codigo, materia.NumeroCreditos);
                        }
                    }
                    for (int i = 0; i < diferencia; i++)
                    {
                        table.Rows.Add("-", "-", "-");
                    }
                    this._vista.TablaMaterias.DataSource = table;
                    this._vista.TablaMaterias.DataBind();
                }
                
            }
            catch (Exception)
            {
                OcurreError(_mensajeError2);//Excepcion
            }
            
        }

        /// <summary>
        /// Al momento de precionar el boton "Continuar" o Refrescar la pagina,  la vista llama al presentador que realiza el
        /// metodo que se encarga de buscar en el gridview de materiasDePensum
        /// y escoge las materias que hallan sido seleccionadas alli
        /// para agregarlas en una lista de materias que se seran enviadas para la segunda etapa
        /// </summary>
        public List<Materia> ObtenerMateriaDePensum()
        {
            List<Materia> listaMateriaAux = new List<Materia>();
            //recorro el gridview y saco la lista de materias seleccionadas
            foreach (GridViewRow row in _vista.TablaMateriasPensum.Rows)
            {
                CheckBox check = row.FindControl("chkSeleccionEscoger") as CheckBox;
                if (check.Checked)
                {
                    Materia mat = new Materia();
                    mat = ObtenerMateriaDeFila(row, mat);
                    listaMateriaAux.Add(mat);
                       
                }
            }
            return listaMateriaAux;
        }

        /// <summary>
        /// Metodo que seencarga de llenar el segundo gridview con las materias seleccionadas por el usuario
        /// </summary>
        public void CargarTablaMateriasParaPensum()
        {
            List<Materia> materias = new List<Materia>();
            materias = _materiasDePensum;//le asigno las materias de pensum
            DataTable table = new DataTable();
            int diferencia = 0;
            table.Columns.Add("Nombre", typeof(string));
            table.Columns.Add("Codigo", typeof(string));
            table.Columns.Add("U.C.", typeof(string));
            try
            {
                if (materias != null)
                {
                    diferencia = Diferencia(materias.Count);
                    LlenarTabla(materias, table, diferencia);
                }
                else
                {
                    LlenarTabla(new List<Materia>(), table, _vista.TablaMateriasPensum.PageSize);
                }

            }
            catch (Exception)
            {
                OcurreError(_mensajeError2);//Excepcion
            }
        }

        /// <summary>
        /// Metodo que se encarga dellenar la tabla de las materias fueron elegidas para armar el pensum
        /// </summary>
        /// <param name="materias"></param>
        /// <param name="table"></param>
        /// <param name="diferencia"></param>
        private void LlenarTabla(List <Materia> materias, DataTable table, int diferencia)
        {
            foreach (Materia materia in materias)
            {
                String nombreMateria = materia.Nombre;
                if (nombreMateria != null)
                {
                    table.Rows.Add(materia.Nombre, materia.Codigo, materia.NumeroCreditos);
                }
            }
            for (int i = 0; i < diferencia; i++)
            {
                table.Rows.Add("-", "-", "-");
            }
            this._vista.TablaMateriasPensum.DataSource = table;
            this._vista.TablaMateriasPensum.DataBind();
        }

        /// <summary>
        /// Metodo que imprime un mensaje en la pagina al ocurrir un error
        /// </summary>
        /// <param name="info">
        /// mensaje de error
        /// </param>
        public void OcurreError(string info)
        {
            _vista.Error.Text = info;
            _vista.Error.ForeColor = System.Drawing.Color.Red;
            _vista.Error.Visible = true;
        }

        /// <summary>
        /// metodo que imprime n mensaje exitoso 
        /// </summary>
        public void OcurreExito()
        {
            _vista.Error.Text =  _mensajeExtio1;
            _vista.Error.CssClass = _trassaccionExitosa;
            _vista.Error.ForeColor = System.Drawing.Color.Green;
            _vista.Error.Visible = true;
        }

        /// <summary>
        /// metodo q valida si hay materias escogidas
        /// </summary>
        public void SiEscogiAlgo()
        {
            _seleccioneAlgo = true;
        }

        #endregion

        #region Constantes

        private const int _numeroFilas = 8;
        private const int _cantidadMinimaDeMaterias = 5;
        private const string _trassaccionExitosa = "transaccionExitosa";
        private const string _paginaActual = "CrearPensumEtapaI.aspx";
        private const string _paginaSiguiente = "CrearPensumEtapaII.aspx";
        private const string _mensajeExtio1 = "Operacion Exitosa: La Materia se escogio exitosamente";
        private const string _mensajeError1 = "Operacion Fallida: Ha Ocurrido un error al Crear el Pensum";
        private const string _mensajeError2 = "Operacion Fallida: Ha Ocurrido una Excepcion Inesperada";
        private const string _mensajeError3 = "Operacion Fallida: Debe seleccionar por lo menos 5 materias";
        private const string _mensajeError4 = "Operacion Fallida: No ha seleccionado ninguna materia";
        private const string _rolUsuario = "Escuela";
        private const string _separador = ": ";

        #endregion

    }
}